package main

// Func0 单一返回值
func Func0(name string) string {
	return "hello,world~"
}

// Func1 Func1多个返回值
func Func1(a, b, c int, str1 string) (string, error) {
	return "", nil
}

// Func2 带名字的返回值
func Func2(a int, b int) (str string, err error) {
	str = "hello"
	//带名字的返回值，可以直接return
	return
}

// Func3 带名字的返回值
func Func3(a int, b int) (str string) {
	res := "hello"
	// 虽然带名字，但是我们并没有用
	return res
}

// 接收返回值
func Invoke() {
	str, err := Func2(1, 2)
	println(str, err)
	// 忽略返回值
	_, _ = Func2(1, 3)
	//部分忽略返回值
	// str是已经声明好了，会报错
	//str, _ := Func2(3, 4)
	// str1 是新变量，需要使用:=
	str1, _ := Func2(3, 4)
	print(str1)
	// str2是新变量,需要使用 ：=
	str2, err := Func2(3, 4)
	println(str2)
}

// Recursive 递归
// 这个方法运行的时候出现错误
func Recursive() {
	Recursive()
}

// 函数式编程入门：方法作为变量
func Func4() {
	myFunc3 := Func3
	_ = myFunc3(1, 2)
}

// 局部方法
func Func5() {
	fn := func(name string) string {
		return "hello, " + name
	}
	println(fn("大明"))
}

// 方法作为返回值
func Func6() func(name string) string {
	return func(name string) string {
		return "hello, " + name
	}
}

func Func6Invoke() {
	sayHello := Func6()
	println(sayHello("大明"))
}

// 匿名方法发起调用
func Func7() {
	hello := func() string {
		return "hello, world"
	}()
	println(hello)
}

// 闭包
func Closure(name string) func() string {
	// 返回的这个函数，就是一个闭包
	// 它引用到了Closure这个方法的入参
	return func() string {
		return "hello, " + name
	}
}

// 不定参数
// YourName不定参数例子
func YourName(name string, alias ...string) {
	if len(alias) > 0 {
		println(alias[0])
	}
}

func YourNameInvoke() {
	YourName("Deng ming")
	YourName("Deng Ming", "Da Ming")
	YourName("Deng Ming", "Da Ming", "Zhong ming")
}

func Defer() {
	defer func() {
		println("第一个defer")
	}()
	defer func() {
		println("第二个defer")
	}()
}

func DeferClosure() {
	i := 0
	defer func() {
		println(i)
	}()
	i = 1 //output 1
}

func DeferClosureV1() {
	i := 0
	defer func(val int) {
		println(val)
	}(i)

	i = 1
}

func DeferReturn() int {
	a := 0
	defer func() {
		a = 1
	}()
	return a
}

func DeferReturnV1() (a int) {
	a = 0
	defer func() {
		a = 1
	}()
	return a
}

type MyStruct struct {
	name string
}

func DeferReturnV2() *MyStruct {
	a := &MyStruct{
		name: "jerry",
	}
	defer func() {
		a.name = "Tom"
	}()
	println(a)
	return a
}

// 自测1 9 8 7...0  结果是10个10
func DeferClosureLoopV1() {
	for i := 0; i < 10; i++ {
		defer func() {
			println(i)
		}()
	}
}

// 自测2 0....7 8 9  结果是 9 8 7...0
func DeferClosureLoopV2() {
	for i := 0; i < 10; i++ {
		defer func(val int) {
			println(val)
		}(i)
	}
}

// 自测3 9 8 7...0 结果是10个1
func DeferClosureLoopV3() {
	for i := 0; i < 10; i++ {
		j := 1
		defer func() {
			println(j)
		}()
	}
}

func main() {
	//Func5()
	//Func6Invoke()
	//Func7()
	//YourNameInvoke()
	//Defer()
	//DeferClosure()
	//DeferClosureV1()
	//DeferReturn()
	//DeferReturnV1()
	//DeferReturnV2()
	//DeferClosureLoopV1()
	//DeferClosureLoopV2()
	DeferClosureLoopV3()
}
